﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using Microsoft.Practices.ServiceLocation;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Windows.Media;
using System.ComponentModel.Composition;
using System.Xml.Linq;

namespace Dynamic_UI_Framework
{
    public class Bench : IBench
    {
        public Bench()
        {
            Items.CollectionChanged += (s, e) => { UIContext.RaiseVisualModified(this); };
        }

        readonly ObservableCollection<IVisual> items = new ObservableCollection<IVisual>();

        public ObservableCollection<IVisual> Items
        {
            get { return items; }
        }

        IVisual currentItem;
        public IVisual CurrentItem {
            get { return currentItem; }
            set {
                this.currentItem = value;
                RaiseCurrentItemChanged();
            }
        }

        public Dock Dock
        {
            get;
            set;
        }

        public string Name
        {
            get;
            set;
        }

        public IVisual Owner
        {
            get;
            set;
        }

        public FrameworkElement Target
        {
            get;
            set;
        }

        public void Activate(IVisual v)
        {
            if (Owner != null)
                Owner.Activate(this);

            if (this.Items.Contains(v))
                this.CurrentItem = v;
        }

        public void Initalize()
        {
            this.Items.CollectionChanged += new System.Collections.Specialized.NotifyCollectionChangedEventHandler(Items_CollectionChanged);

            UserControl u = this.Target as UserControl;
            if (u != null)
            {
                List<MenuItem> mi = GetMenuItem();
                u.ContextMenu = new ContextMenu();
                foreach (var item in mi)
                {
                    u.ContextMenu.Items.Add(item);
                }
            }
        }

        void Items_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
        {
            if (e.Action == NotifyCollectionChangedAction.Add)
            {
                this.CurrentItem = e.NewItems[0] as IVisual;
            }
            else
            {
                if (this.Items.Contains(this.CurrentItem))
                    return;

                this.CurrentItem = this.Items[this.Items.Count - 1];
            }
        }

        public List<MenuItem> GetMenuItem()
        {
            List<MenuItem> list = new List<MenuItem>();
            LayoutAdapterMapping layoutMapping = ServiceLocator.Current.GetInstance<LayoutAdapterMapping>();
            MenuItem layoutMenu = new MenuItem { Header = layoutMapping.Name };
            foreach (var item in layoutMapping.Mappings)
            {
                MenuItem mi = new MenuItem();
                mi.Header = item.Key.Name;
                mi.Tag = item.Value;
                mi.Click += (s, e) =>
                {
                    IAdapter adapter = mi.Tag as IAdapter;
                    if (adapter == null)
                        return;

                    DockPanel dock = new DockPanel();
                    dock.Background = Brushes.Red;

                    string name = DialogHelper.DialogName(string.Empty);
                    if (string.IsNullOrEmpty(name))
                        return;

                    IVisual v= adapter.Initialize(dock, name) as IVisual;
                    v.Owner = this;
                    this.Items.Add(v);
                };
                layoutMenu.Items.Add(mi);
            }
            list.Add(layoutMenu);


            RegionAdapterMapping mappint = ServiceLocator.Current.GetInstance<RegionAdapterMapping>();
            MenuItem regionMenu = new MenuItem { Header = mappint.Name };

            RegionController rc = ServiceLocator.Current.GetInstance<RegionController>();
            foreach (var path in rc.Paths)
            {
                MenuItem mi = new MenuItem();
                mi.Header = path.Key;
                mi.Tag = path.Value;
                mi.Click += (s, e) =>
                {
                    UINode node = new UINode();
                    node.LoadXml((s as MenuItem).Tag as XElement);
                    IBuilder builder = ServiceLocator.Current.GetInstance<IBuilder>(node.TypeName);
                    IVisual v = builder.Build(node);
                    v.Owner = this;
                    this.items.Add(v);
                };
                regionMenu.Items.Add(mi);
            }
            list.Add(regionMenu);
            return list;
        }

        void RaiseCurrentItemChanged()
        {
            var hander = this.CurrentItemChanged;
            if (hander != null)
                hander(this, null);

        }

        public event EventHandler CurrentItemChanged;
    }


    [Export("Bench", typeof(IBuilder))]
    public class BenchBuilder : IBuilder
    {
        public UINode GetUINode(IVisual obj)
        {
            Bench bench = obj as Bench;
            if (bench == null)
                return null;

            UINode node = new UINode();
            node.Target = bench;
            node.TypeName = bench.GetType().Name;
            node.Name = bench.Name;
            node.Properties.Add("target", bench.Target.GetType().FullName);

            foreach(var item in bench.Items)
            {
                string key = item.GetType().Name;
                IBuilder builder = ServiceLocator.Current.GetInstance<IBuilder>(key);
                if (builder == null)
                    throw new Exception("builder == null");

                UINode child = builder.GetUINode(item);
                child.Owner = node;
                node.Children.Add(child);
            }
            return node;
        }
        public IVisual Build(UINode node)
        {
            string target = node.Properties.ContainsKey("target") ? node.Properties["target"].ToString() : null;
            if (string.IsNullOrEmpty(target))
                throw new Exception("string.IsNullOrEmpty(typeFullName)");

            BenchAdapterMapping mapping = ServiceLocator.Current.GetInstance<BenchAdapterMapping>();
            IAdapter adapter = mapping.GetMappingByTypeFullName(target);
            if (adapter == null)
                throw new Exception("adapter == null");

            Bench bench = adapter.DefaultBuild(node.Name) as Bench;
            foreach (var item in node.Children)
            {
                IBuilder builder = ServiceLocator.Current.GetInstance<IBuilder>(item.TypeName);
                IVisual child = builder.Build(item) as IVisual;
                child.Owner = bench;
                bench.Items.Add(child);
            }
            return bench;
        }
    }
}
